/*
 * @Description: In User Settings Edit
 * @Author: yanmeiyang
 * @Date: 2019-08-19 18:37:08
 * @LastEditTime: 2021-09-17 15:58:25
 * @LastEditors: junjun
 */
/* eslint-disable no-param-reassign */
// TODO 这里只是trends的一些提取出来的方法。

import React from 'react';
import { FM } from 'locales';
import strings from 'utils/strings';
import { _pointOnPath } from './curve';
import { getYears } from '@/utils/trendUtils';
import { colorList } from '@/pages/topic/chart/show/phone/TrendStaticChart.js';
const yearToXOffset = (trendData, width, year, startYear, endYear) => {
  // Math.floor((year - trendData.startYear) / trendData.time_slides[0].length);
  // const slideOld = trendData.yearToSlide[year];
  const startSlide = getSlideByYear(trendData, startYear); // 获取当前开始年份的块号
  const endSlide = getSlideByYear(trendData, endYear);
  const slide = getSlideByYear(trendData, year); // 获取理应位于的块号
  const years = trendData.time_slides[slide]; // 获取改块中的所有年份
  const offset = years.indexOf(parseInt(year)) > 0 ? years.indexOf(parseInt(year)) : 0; // 该年位于该块中的第几个
  const binWidth = width / (endSlide - startSlide + 1); // 获取每一块的宽度
  const binOffset = slide - startSlide + (offset + 1) / years.length;
  return binWidth * binOffset;
};

const getSlideByYear = (trendData, year) => {
  return Math.floor((parseInt(year) - trendData.startTime) / trendData.time_slides[0].length);
};

// 暂时还是用老的逻辑
const makeMessage = ({ query, loadingFlag, errorFlag, tip }) => {
  let msg = '';
  query = strings.cleanQuery(query);
  const values = {
    tip,
  };
  if (errorFlag) {
    if (!query || query === '-') {
      msg = (
        <FM
          id="com.topTrend.emptyInfo"
          values={values}
          defaultMessage="Please input or select a keyword!"
        />
      );
    } else {
      msg = (
        <FM
          id="com.topTrend.errorInfo"
          values={values}
          defaultMessage="Technology prediction about '{tip}' does not exist or input error. Please check."
        />
      );
    }
  } else if (loadingFlag) {
    msg = (
      <FM
        id="com.topTrend.info"
        values={values}
        defaultMessage="Technology prediction about '{tip}' is analyzing. Please wait."
      />
    );
  }
  return msg;
};

const getInfo = (links, trendData, d3, width, startYear, endYear) => {
  var boards = [];
  var mids = [];
  const baseWidthPerPoint = 50;
  var curvature = 0.5;
  links.forEach(d => {
    const myTerm = trendData.terms.filter(item => item.t == d.source.term);
    const term = myTerm[0];
    if (!term) return;

    var rate = 1;
    if (term.hasOwnProperty('rate')) {
      rate = term['rate'];
    }

    var widthPerPoint = Math.round(baseWidthPerPoint * rate);
    var maxCount = Math.ceil((d.dy1 + d.dy2) / (widthPerPoint * 2));

    // for (var year = trendData.startTime; year <= trendData.endTime; year++) {
    //   total_info[year] = {};
    // }
    let total_info = {};
    //按年份整理
    if (term.selected && term.pubs && term.pubs.length > 0) {
      term.pubs.forEach(record => {
        var year = record.year;
        if (total_info[year] === undefined) {
          total_info[year] = {};
        }
        total_info[year][record.id] = record;
      });
    }
    // if (term.hasOwnProperty('pub')) {
    //   term.pub.forEach(record => {
    //     var year = record.year;
    //     total_info[year][record.id] = record;
    //   });
    // }

    //根据宽度确定点的个数
    for (var year in total_info) {
      var counts = 0;
      var keys = Object.keys(total_info[year]);
      if (keys.length > maxCount) {
        keys.sort((a, b) => {
          return total_info[year][a].Score > total_info[year][b].Score;
        });
        keys = keys.slice(0, maxCount);

        for (var id in total_info[year]) {
          if (!keys.includes(id)) {
            delete total_info[year][id];
          }
        }
      }

      for (var id in total_info[year]) {
        counts += 1;
        var x0 = d.source.x + d.source.dx,
          x1 = d.target.x,
          xi = d3.interpolateNumber(x0, x1),
          xj = d3.interpolateNumber(x1, x0),
          x2 = xi(curvature),
          x3 = xi(1 - curvature),
          y0_top = d.source.y + d.sy,
          y1_top = d.target.y + d.ty,
          y0_bottom = d.source.y + d.sy + d.dy1,
          y1_bottom = d.target.y + d.ty + d.dy2;

        var lambda = counts / (Object.keys(total_info[year]).length + 1 - counts);
        var y0_mid = (y0_top + y0_bottom * lambda) / (1 + lambda),
          y1_mid = (y1_top + y1_bottom * lambda) / (1 + lambda);

        var curve = [
          {
            x: x0,
            y: y0_mid,
          },
          {
            x: x2,
            y: y0_mid,
          },
          {
            x: x3,
            y: y1_mid,
          },
          {
            x: x1,
            y: y1_mid,
          },
        ];

        var absolute = yearToXOffset(trendData, width, year, startYear, endYear);
        if (absolute > x0 && absolute <= x1) {
          var location = 1 - (absolute - x0) / (x1 - x0);
          var first_author_withid = null;
          var authors = total_info[year][id].authors;
          if (authors === undefined) {
            authors = [];
            total_info[year][id].authors = [];
          }
          for (var i = 0; i < authors.length; i++) {
            if (authors[i].hasOwnProperty('id')) {
              first_author_withid = authors[i].id;
              break;
            }
          }

          const info = {
            posi: _pointOnPath(curve, location),
            public: total_info[year][id],
            author: first_author_withid,
            year: year,
            groupID: d.groupID,
          };

          mids.push(info);

          var curveBoard = [
            {
              x: x0,
              y: y0_top,
            },
            {
              x: x2,
              y: y0_top,
            },
            {
              x: x3,
              y: y1_top,
            },
            {
              x: x1,
              y: y1_top,
            },
          ];
          boards.push(_pointOnPath(curveBoard, location));
          curveBoard = [
            {
              x: x0,
              y: y0_bottom,
            },
            {
              x: x2,
              y: y0_bottom,
            },
            {
              x: x3,
              y: y1_bottom,
            },
            {
              x: x1,
              y: y1_bottom,
            },
          ];
          boards.push(_pointOnPath(curveBoard, location));
        }
      }
    }
  });
  return [mids, boards];
};

const Upper = str => {
  try {
    return str.toLowerCase().replace(/( |^)[a-z]/g, L => L.toUpperCase());
  } catch {
    return str;
  }
};

const linkNode = (trendData, defaultSelect, startYear, endYear) => {
  if ((!startYear && startYear !== 0) || !trendData || !trendData.terms) return;
  const nodes = [];
  const links = [];
  const selectedTerms = {};
  let cnt = 0;
  let colorMap = {};
  let colorIndex = 0;
  let colorArray =colorList;
  let initYear = endYear;
  for (const term of trendData.terms) {
    if (trendData.unchoosed) {
      if (cnt < defaultSelect) term.selected = true;
      else term.selected = false;
    }

    if (term.selected) {
      selectedTerms[term.t] = true;
      colorMap[term.t] = colorArray[colorIndex];
      colorIndex++;
      if (colorIndex >= 10) {
        colorIndex = 0;
      }
    }
    cnt += 1;
  }
  let tempTermFreqBySlide = trendData.term_freq_by_slide;
  let i = 0;
  let j = trendData.time_slides.length;
  trendData.time_slides &&
    trendData.time_slides.map((row, index) => {
      if (row.includes(startYear)) {
        i = index;
      }
      if (row.includes(endYear)) {
        j = index;
      }
    });
  tempTermFreqBySlide = trendData.term_freq_by_slide.slice(i, j + 1);
  const nodeMap = {};
  let nodeindex = 0;

  tempTermFreqBySlide.forEach((termFreqMap, index) => {
    Object.keys(termFreqMap).forEach((keyword, ind) => {
      if (selectedTerms[keyword]) {
        if (!nodeMap[keyword]) {
          nodeMap[keyword] = [];
        }
        const termFreq = termFreqMap[keyword];
        const label = trendData.term_to_label[keyword];

        let heat = termFreq;
        const _aX = 0.1;
        const _aP = 0.5;
        const preFreq = nodeMap[keyword].slice(-1)[0]?.pubs;

        if (index > 0 && preFreq) heat = (heat + _aX * preFreq) / (1 + _aX);
        heat = Math.pow(heat, _aP);

        nodeMap[keyword].push({
          id: nodeindex++,
          name: label,
          term: keyword,
          pubs: termFreq,
          w: Math.pow(termFreq, 0.5),
          total: tempTermFreqBySlide.length,
          pos: index,
        });
        nodes.push({
          name: label,
          term: label || keyword,
          pubs: termFreq,
          color: colorMap[keyword],
          w: Math.pow(termFreq, 0.5),
          // w: heat,
          total: tempTermFreqBySlide.length,
          pos: index,
        });
      }
    });
  });
  for (let keyword in nodeMap) {
    for (let i = 0; i < nodeMap[keyword].length - 1; i++) {
      links.push({
        firsrt: i == 0,
        source: nodeMap[keyword][i].id,
        target: nodeMap[keyword][i + 1].id,
        w1: nodeMap[keyword][i].w,
        w2: nodeMap[keyword][i + 1].w,
        color: colorMap[keyword],
        // yearrange: 'hahahhahaha',
        // groupID: group,
      });
    }
  }
  return [nodes, links, initYear];
};

const linkNodeNew = (trendData, defaultSelect, startYear, endYear) => {
  if ((!startYear && startYear !== 0) || !trendData || !trendData.terms) return;

  const nodes = [];
  const links = [];
  const selectedTerms = {};
  let cnt = 0;
  let colorMap = {};
  let colorIndex = 0;
  let colorArray = colorList;
  let initYear = endYear;
  for (const term of trendData.terms) {
    if (trendData.unchoosed) {
      if (cnt < defaultSelect) term.selected = true;
      else term.selected = false;
    }

    if (term.selected) {
      selectedTerms[term.t] = true;
      colorMap[term.t] = colorArray[colorIndex];
      colorIndex++;
      if (colorIndex >= 10) {
        colorIndex = 0;
      }
    }
    cnt += 1;
  }

  const freqYearMap = {};
  for (let i = startYear; i <= endYear; i++) {
    freqYearMap[i] = {};
    Object.keys(selectedTerms).forEach(key => {
      const freq = trendData.term_freq_by_year[key];
      freqYearMap[i][key] = freq[i];
    });
  }

  const nodeMap = {};
  let nodeindex = 0;

  const { yearArr, q } = getYears(startYear, endYear);
  yearArr.forEach((year, i) => {
    const curYear = year;
    let termFreqMap = freqYearMap[year];
    if (!termFreqMap) return;
    Object.keys(termFreqMap).forEach((term, index) => {
      if (!nodeMap[term]) {
        nodeMap[term] = [];
      }
      let freq = termFreqMap[term] || 0;
      if (i > 0) {
        const preYear = nodeMap[term][i - 1].year;
        if (curYear - preYear > 1) {
          for (let i = preYear + 1; i < curYear; i++) {
            freq += freqYearMap[i][term] || 0;
          }
        }
      }
      const label = trendData.term_to_label[term];

      let heat = freq;

      if (i > 0) {
        const _aX = 3;
        const preNode = nodeMap[term].slice(-1)[0];
        let preFreq = preNode?.pubs || 0;
        if (heat <= 0 && preFreq === 0) {
          preFreq = preNode?.w || 0;
        }
        heat = (heat + _aX * preFreq) / (1 + _aX);
      }

      const _aP = 0.5;
      heat = Math.pow(heat, _aP);

      nodeMap[term].push({
        id: nodeindex++,
        name: label,
        term: term,
        pubs: freq,
        w: heat,
        total: q,
        pos: i,
        col: i,
        year: curYear,
      });
      nodes.push({
        name: label,
        term: label || term,
        pubs: freq,
        color: colorMap[term],
        // w: Math.pow(freq, 0.5),
        w: heat,
        total: q,
        pos: i,
        col: i,
        year: curYear,
      });
    });
  });

  for (let keyword in nodeMap) {
    for (let i = 0; i < nodeMap[keyword].length - 1; i++) {
      links.push({
        firsrt: i == 0,
        source: nodeMap[keyword][i].id,
        target: nodeMap[keyword][i + 1].id,
        w1: nodeMap[keyword][i].w,
        w2: nodeMap[keyword][i + 1].w,
        color: colorMap[keyword],
      });
    }
  }
  return { nodes, links, initYear, q, yearArr };
  // return [nodes, links, initYear];
};

const linkNode2 = (trendData, defaultSelect, startYear, endYear) => {
  if (!startYear) return;
  const nodes = [];
  const links = [];
  const nodeToIndex = {};
  const selectedTerms = {};
  const addedTerms = {};
  const termToChild = {};
  const termToGroup = {};
  let initYear = endYear;
  let cnt = 0;
  let colorMap = {};
  let colorIndex = 0;
  let colorArray = ['white'];;
  if (!trendData || !trendData.terms) return;
  for (const term of trendData.terms) {
    if (trendData.unchoosed) {
      if (cnt < defaultSelect) term.selected = true;
      // 默认选中前12个
      else term.selected = false;
    }

    if (term.selected) {
      selectedTerms[term.t] = true;
      colorMap[term.t] = colorArray[colorIndex];
      colorIndex++;
      if (colorIndex >= 10) {
        colorIndex = 0;
      }
    }
    cnt += 1;
  }

  const { term_freq_by_slide, time_slides } = trendData;
  const slideToYear = time_slides || {};

  const groups = [];
  let groupNum = 0;
  let tempTermFreqBySlide = trendData.term_freq_by_slide;
  let i = 0;
  time_slides.map((row, index) => {
    if (row.includes(startYear)) {
      i = index;
    }
  });
  if (i > 0) {
    tempTermFreqBySlide = trendData.term_freq_by_slide.slice(i);
  }
  for (let i = 0; i < tempTermFreqBySlide.length; i++) {
    var index = i < tempTermFreqBySlide.length ? i : i - 1;
    for (const key of Object.keys(selectedTerms)) {
      let termFreq = 0.0;

      // 获取选定词组的最早年份
      for (let year in trendData.term_freq_by_year[key]) {
        if (initYear > year) {
          initYear = year;
        }
      }
      // 此处为每个词每一块的词频
      termFreq = tempTermFreqBySlide[index][key];

      if (addedTerms[key] || termFreq) {
        let freq = termFreq || 0.5;
        if (slideToYear[index] && slideToYear[index].length > 0) {
          freq = (termFreq || 0.5) / slideToYear[index].length;
        }

        const preNode = nodes[nodeToIndex[`${key}-${i - 1}`]];
        if (preNode !== undefined) {
          freq = (freq + 0.1 * preNode.w) / 1.1;
        } else {
          freq = freq * 2;
        }
        const n = {
          name: trendData.term_to_label[key],
          term: key,
          pubs: termFreq,
          w: Math.pow(freq, i == tempTermFreqBySlide.length - 1 ? 0.5 : 0.5),
          total: tempTermFreqBySlide.length,
          pos: i,
        };
        if (!addedTerms[key]) {
          n.first = true;
          addedTerms[key] = true;
        }

        nodeToIndex[`${key}-${i}`] = nodes.length;
        nodes.push(n);

        let group = -1;
        const preIndex = nodeToIndex[`${key}-${i - 1}`];
        if (preIndex !== undefined) {
          group = groups[preIndex];
        } else {
          groupNum += 1;
          group = groupNum;
        }
        groups.push(group);
        if (i >= 0 && preNode !== undefined) {
          links.push({
            source: nodeToIndex[`${key}-${i - 1}`],
            target: nodeToIndex[`${key}-${i}`],
            w1: preNode.w,
            w2: n.w,
            color: colorMap[key],
            yearrange:
              slideToYear[index] && slideToYear[index].length > i
                ? `(${slideToYear[index][i] - 1}~${
                    slideToYear[index][i] + slideToYear[index].length - 1
                  })`
                : '',
            // groupID: group,
          });
        }
        // }
      }
    }
  }
  return [nodes, links, initYear];
};

// const pointAni = (d3,point) => {
//   var scale = d3.scaleLinear();
//   scale.domain([0, 1000, 2000])
//     .range([0, 1, 0]);
//   var start = Date.now();
//   d3.timer(function () {
//     var s1 = scale((Date.now() - start) % 2000);
//     point.attr("stroke-opacity", s1);
// }

const makeSense = obj => {
  return typeof obj !== 'undefined' && obj !== null;
};

//排序
const sortTerms = (method, trendData) => {
  const sortFuncs = {
    recent: term => term.y > 2012 && term.d > 0,
    origin: term => getSlideByYear(trendData, term.y) <= 3,
  };

  var maxSum = 0;
  const filterFunc = sortFuncs[method] || (() => true);

  // current hotsopt中按各技术2010年之后的文献总数排序
  trendData.terms.forEach(t => {
    t.sum = 0;
    t.year.forEach(tt => {
      if (filterFunc(tt)) {
        t.sum += tt.d;
      }
    });
    if (t.sum > maxSum) {
      maxSum = t.sum;
    }
    // terms[t.t] = t;
  });

  trendData.terms.sort((a, b) => b.sum - a.sum);
  const selectedTerm = trendData.terms[0];

  return [trendData, selectedTerm, maxSum];
};

const setVisible = infos => {
  for (const id in infos) {
    const vis = infos[id];
    const tabselm = document.getElementById(id);
    if (tabselm) {
      tabselm.style.display = vis ? '' : 'none';
    }
  }
};

const getVisible = id => {
  const tabselm = document.getElementById(id);
  return tabselm.style.display != 'none';
};

export {
  yearToXOffset,
  makeMessage,
  _pointOnPath,
  getInfo,
  linkNode,
  linkNodeNew,
  Upper,
  makeSense,
  sortTerms,
  setVisible,
  getVisible,
};

// --------------
const test = () => {
  const d3 = {};

  const formatNumber = d3.format(',.0f');

  const format = d => {
    // 格式化为整数，点出现的次数
    return `${formatNumber(d)} Times`;
  };
};
